package parallel.project.solver;

import parallel.project.graph.Edge;
import parallel.project.graph.Graph;
import parallel.project.graph.Node;

/**
 * Event that is created by a {@link SolverSlave} to alert either its
 * {@link SolverMaster} or someone else of what it is doing
 * 
 * @author Adam Clayton
 * @author Larry Walters
 */
public class SlaveNotificationEvent 
{	
	/** The slave this event is happening on */
	SolverSlave slave;
	
	/** The type of event */
	EventType type;
	
	/** Node associated with this event, if any */
	Node node;
	
	/** Edge associated with this event, if any */
	Edge edge;
	
	/** Graph associated with this event, if any */
	Graph graph;
	
	/** A message associated with this event */
	String msg;
	
	/**
	 * Creates a new notification event which is from the given 
	 * {@link SolverSlave} and has to do with the given {@link Node} 
	 * and {@link Edge}.
	 * 
	 * @param slave
	 * 		Slave this event is associated with
	 * @param type
	 * 		The type of event this is (what it is telling)
	 * @param node
	 * 		The {@link Node} associated with this event, if any
	 * @param edge
	 * 		The {@link Edge} associated with this event, if any
	 * @param msg
	 * 		Some message associated with this event
	 */
	public SlaveNotificationEvent(SolverSlave slave, EventType type,
		Node node, Edge edge, String msg)
	{
		this.slave = slave;
		this.type = type;
		this.node = node;
		this.edge = edge;
		this.msg = msg;
		this.graph = null;
	}
	
	/**
	 * Creates a new notification event which is from the given 
	 * {@link SolverSlave} and has to do with the given {@link Graph}.
	 * 
	 * @param slave
	 * 		Slave this event is associated with
	 * @param type
	 * 		The type of event this is (what it is telling)
	 * @param graph
	 * 		The {@link Graph} associated with this event, if any
	 * @param msg
	 * 		Some message associated with this event
	 */
	public SlaveNotificationEvent(SolverSlave slave, EventType type,
		Graph graph, String msg)
	{
		this.slave = slave;
		this.type = type;
		this.node = null;
		this.edge = null;
		this.msg = msg;
		this.graph = graph;
	}
	
	/**
	 * Defines the reason for this event, what the event is indicating.
	 */
	public enum EventType
	{
		/** The slave has arrived at a new {@link Node} and is now 
		 * proceeding on a certain path, indicated by an {@link Edge} */
		LOCATION_UPDATE,
		/** The slave has reached the end {@link Node}, thus solving the
		 * maze */
		MAZE_SOLVED,
		/** The slave has created a graph of the whole maze */
		GRAPH_COMPLETED,
		/** Some debug or other message */
		MSG
	}
	
	/**
	 * Convenience method to create an update location event.
	 * 
	 * @param slave
	 * 		Slave who is notifying this update in location
	 * @param node
	 * 		The {@link Node} the slave has just arrived at
	 * @param edge
	 * 		The {@link Edge} the slave is now proceeding along away
	 * 		from that {@link Node} (the path it has decided to take 
	 * 		from the {@link Node}
	 * @param msg
	 * 		Some message associated with this update
	 * 
	 * @return
	 * 		Update location event
	 */
	public static SlaveNotificationEvent updateEvent(SolverSlave slave,
		Node node, Edge edge, String msg)
	{
		return new SlaveNotificationEvent(slave,
					EventType.LOCATION_UPDATE,node,edge,msg);
	}
	
	/**
	 * Convenience method to create a solved event.  There is no
	 * {@link Edge} associated with this, so it is null.
	 * 
	 * @param slave
	 * 		Slave who has just solved the maze
	 * @param node
	 * 		The finishing {@link Node} the slave has reached
	 * @param msg
	 * 		Some message associated with this update
	 * 
	 * @return
	 * 		Maze solved event
	 */
	public static SlaveNotificationEvent solvedEvent(SolverSlave slave,
		Node node, String msg)
	{
		return new SlaveNotificationEvent(slave,
					EventType.MAZE_SOLVED,node,null,msg);
	}

	/**
	 * Convenience method to create a graph completed event.
	 * 
	 * @param slave
	 * 		Slave who has just completed the graph
	 * @param graph
	 * 		The {@link Graph} the slave has created
	 * @param msg
	 * 		Some message associated with this event
	 * 
	 * @return
	 * 		Graph of maze completed event
	 */
	public static SlaveNotificationEvent graphMadeEvent(
		SolverSlave slave, Graph graph, String msg)
	{
		return new SlaveNotificationEvent(slave,
					EventType.GRAPH_COMPLETED,graph,msg);
	}
	
	/**
	 * Convenience method to create a message event.  There is no
	 * {@link Node} nor {@link Edge} associated with this, so they are
	 * null.  If you want to include them, you must make the event
	 * directly.
	 * 
	 * @param slave
	 * 		Slave sending this message
	 * @param msg
	 * 		The message
	 * 
	 * @return
	 * 		Message event
	 */
	public static SlaveNotificationEvent msgEvent(SolverSlave slave,
		String msg)
	{
		return new SlaveNotificationEvent(slave,
					EventType.MSG,null,null,msg);
	}
}
